﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;

namespace DCRF.Common.Support
{
    /// <summary>
    /// A simple typtless table used to transfer complex data types (e.g. hashtable)
    /// This is a lightweight, serializable and marshalable data sutrcture
    /// </summary>
    public class SimpleTable
    {
        private List<string> keys = new List<string>();
        private List<Type> types = new List<Type>();
        private List<SimpleRow> values = new List<SimpleRow>();

        public SimpleTable()
        {
        }

        public List<SimpleRow> Rows
        {
            get
            {
                return values;
            }
        }

        public SimpleTable(params object[] ks)
        {
            AddKeys(ks);
        }

        public List<string> Keys
        {
            get
            {
                return keys;
            }
        }

        public List<Type> Types
        {
            get
            {
                return types;
            }
        }

        public void AddKeys(params object[] ks)
        {
            for(int i=0;i<ks.Length;i+=2)
            {
                string key = ks[i].ToString();
                Type type = ks[i+1] as Type;

                Keys.Add(key);
                Types.Add(type);
            }
        }

        public SimpleRow AddRow()
        {
            SimpleRow result = new SimpleRow(this);

            values.Add(result);

            return result;
        }

        public SimpleRow AddRow(params object[] values)
        {
            SimpleRow result = AddRow();

            for (int i = 0; i < values.Length; i++)
            {
                result[i] = values[i];
            }

            return result;
        }

        public void DeleteRow(SimpleRow row)
        {
            values.Remove(row);
        }

        public SimpleRow this[int index]
        {
            get
            {
                DBC.Check.Require(values.Count > index);


                return values[index];
            }
        }
        public int Count
        {
            get
            {
                return values.Count;
            }
        }
    }

    public class SimpleRow
    {
        private SimpleTable parent = null;
        private List<object> values = new List<object>();

        public SimpleRow(SimpleTable p)
        {
            parent = p;
        }

        public SimpleRow Clone()
        {
            SimpleRow row = new SimpleRow(this.parent);
            row.values.InsertRange(0, this.values);

            return row;
        }

        public SimpleTable Parent
        {
            get
            {
                return parent;
            }
        }

        public object this[int index]
        {
            get
            {
                if ( parent != null ) DBC.Check.Require(index < parent.Keys.Count);
                DBC.Check.Require(index != -1);

                if (index < values.Count)
                {
                    return values[index];
                }

                return null;
            }
            set
            {
                if (parent != null) DBC.Check.Require(index < parent.Keys.Count);
                DBC.Check.Require(index != -1);

                Type t = null;

                if (parent != null)
                {
                    t = parent.Types[index];
                }

                //if (value != null && !value.GetType().Equals(t))
                //{
                //    throw new Exception("Invalid type for " + parent.Keys[index]);
                //}

                if (index >= values.Count)
                {
                    for (int i = values.Count; i <= index; i++)
                    {
                        values.Add(null);
                    }
                }

                if (value == null)
                {
                    values[index] = null;
                }
                else
                {
                    if (parent != null)
                    {
                        values[index] = Convert.ChangeType(value, t); ;
                    }
                    else
                    {
                        values[index] = value;
                    }
                }
            }
        }

        public object this[string key]
        {
            get
            {
                DBC.Check.Require(parent != null);
                int index = parent.Keys.IndexOf(key);

                return this[index];
            }
            set
            {
                DBC.Check.Require(parent != null);
                int index = parent.Keys.IndexOf(key);

                this[index] = value;
            }
        }
    }
}

